package oracle.olapi.examples;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;


abstract public class BaseExample {
    
    static public final String KEY_LOGFILE = "logfile";
    static final public String VALUE_YES = "yes";
    static final public String KEY_VERBOSE = "verbose";
    
    private CursorPrintWriter cpw;
    private Logger logger;
    
    /**
     * Implement this method for an example class
     */
    protected abstract void run() throws Exception;
    
    /**
     * execute the example and report all exceptions to the caller.
     * This method is public so that it can be called from a test framework.
     */
    public void execute(Properties properties) {
        // Note that we are not handling any exceptions here.
        // This is for the caller to do.
        // However, we make sure the example framework is shut down properly.
        try {
            initialize(properties);
            run();
        } catch ( Exception e ) {
            printStackTrace(e);
        } finally {
            shutdown();
        }
    }
    
    /**
     * Convinience method to permit easy execution of an example
     * by the main() method defined in a source file
     */
    public void execute(String[] args) {
        String[] jdbc = new String[] {"-url", "jdbc:oracle:thin:@NAI02DRO.mt.att.com:1525:NAI02DRO",
            	"-user", "global", "-password", "dusk_2_dawn"};
        execute(convertToProperties(jdbc));
    }
    
    protected void initialize(Properties properties)
    throws Exception {
        setUpCursorPrintWriter(properties);
        setupLogger(getCursorPrintWriter(), properties);
    }
    
    protected void shutdown() {
        logger.close();
        logger = null;
        closeCursorPrintWriter();
    }
    
    final void setupLogger(PrintWriter writer, Properties properties) {
        logger = ( writer == null
                ? new Logger()
                : new Logger(writer) );
        boolean verbose =
                VALUE_YES.equalsIgnoreCase( properties.getProperty(KEY_VERBOSE));
        logger.setVerbose(verbose);
    }
    
    protected final Logger getLogger() {
        return logger;
    }
    
    
    final void setUpCursorPrintWriter(Properties properties)
    throws IOException {
        
        String logFile = properties.getProperty(KEY_LOGFILE);
        if ( null == logFile ) {
            cpw = CursorPrintWriter.getStandardOutput(); // default to Stdout
        } else {
            PrintWriter writer = new PrintWriter(new FileWriter(logFile));
            cpw = new CursorPrintWriter(writer);
        }
    }
    
    protected CursorPrintWriter getCursorPrintWriter() {
        return cpw;
    }
    
    final void closeCursorPrintWriter() {
        if ( cpw != null )
            cpw.close();
        cpw = null;
    }
    
    void printStackTrace(Exception e) {
        if ( null != cpw )
            e.printStackTrace(cpw);
    }
    
    protected void println(String line) {
        cpw.println(line);
    }
    
    protected void println() {
        cpw.println();
    }
    
    protected void print(String line) {
        cpw.print(line);
    }
    
    protected void print(Object obj) {
        cpw.print(obj);
    }
    
    /**
     * Convert the command-line arguments used to run the example program
     * into a Properties object
     *
     * @param args A String array that contains the command-line arguments.
     */
    static public Properties convertToProperties(String args[]) {
        Properties props = new Properties();
        for (int i = 0; i < args.length; i += 2) {
            if (i + 1 == args.length ||
                    !args[i].startsWith("-") ) {
                throw new IllegalArgumentException("Command-line arguments must be " +
                        "specified in the form -<property> <value> [...], " +
                        "with name and value separated by whitespace.");
            }
            props.put(args[i].substring(1), args[i + 1]);
        }
        return props;
    }
    
    
}
